﻿package com.simarsoft.common.util;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 用于验证字串是否和预定义格式匹配
 * 创建日期：2009-10-20
 * 更新日期：2009-10-21
 *@author Harrison.Ma
 *@version 1.0
 */
public class SimpleParser {

	/*IPv4*/
	private static final String IPv4_PATTERN = "^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])$";
	/*IPv6*/
	private static final String IPv6_PATTERN = "^(^((\\p{XDigit}{1,4}):){7}(\\p{XDigit}{1,4})$)|(^(\\p{XDigit}{1,4})?::(\\p{XDigit}{1,4})$)|(^((\\p{XDigit}{1,4}):){0,5}(\\p{XDigit}{1,4})::(\\p{XDigit}{1,4})$)$";
	/*MAC地址*/
	private static final String MAC_PATTERN = "([0-9A-Fa-f]{2})(-[0-9A-Fa-f]{2}){5}";
	/*电子邮件地址*/
	private static final String EMAIL_PATTERN = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
	/*移动电话号码*/
	private static final String MOBPHONE_PATTERN = "^[1][3,5]+\\d{9}";
	/*固定电话号码*/
	private static final String TELPHONE_PATTERN = "\\d{4}-\\d{8}|\\d{4}-\\d{7}|\\d(3)-\\d(8)";
	/*数字验证，字首可为0*/
	private static final String DIGITAL_PATTERN = "^[0-9]*$";
	/*字符验证，可含有下划线*/
	private static final String ALLCHAR_PATTERN = "[a-zA-Z_]*$";
	/*邮政编码*/
	private static final String POSTCODE_PATTERN = "[1-9]\\d{5}(?!\\d)";
	/*中文*/
	private static final String WORD_CN_PATTERN = "^[\u4e00-\u9fa5]+$";
	
	/**
	 * 验证IPv4
	 * @param ipv4
	 * @return
	 */
	public static boolean parseIPv4(String ipv4) {
		return customParse(ipv4, IPv4_PATTERN);
	}
	
	/**
	 * 验证IPv6
	 * @param ipv6
	 * @return
	 */
	public static boolean parseIPv6(String ipv6) {
		return customParse(ipv6, IPv6_PATTERN);
	}
	
	/**
	 * 验证电脑MAC地址
	 * @param mac
	 * @return
	 */
	public static boolean parseMAC(String mac) {
		return customParse(mac, MAC_PATTERN);
	}
	
	/**
	 * 验证电子邮箱地址
	 * @param email
	 * @return
	 */
	public static boolean parseEmail(String email) {
		return customParse(email, EMAIL_PATTERN);
	}
	
	/**
	 * 验证中国大陆固定电话号码
	 * @param phoneNumber
	 * @return
	 */
	public static boolean parseTelPhone(String phoneNumber) {
		return customParse(phoneNumber, TELPHONE_PATTERN);
	}
	
	/**
	 * 验证手机号
	 * @param phoneNumber
	 * @return
	 */
	public static boolean parseMobPhone(String phoneNumber) {
		return customParse(phoneNumber, MOBPHONE_PATTERN);
	}
	
	/**
	 * 验证中国身份证号
	 * @param idCard
	 * @return
	 */
	public static boolean parseIDCard(String idCard) {
		
		return ParserServiceIDCARD.validate(idCard);
	}
	
	/**
	 * 验证中国邮政编码
	 * @param postcode
	 * @return
	 */
	public static boolean parsePostcode(String postcode) {
		return customParse(postcode, POSTCODE_PATTERN);
	}
	
	/**
	 * 验证是否都为数字
	 * @param value
	 * @return
	 */
	public static boolean parseDigital(String value) {
		return customParse(value, DIGITAL_PATTERN);
	}
	
	/**
	 * 验证是否都是ASCII制英文字符
	 * @param value
	 * @return
	 */
	public static boolean parseChar(String value) {
		return customParse(value, ALLCHAR_PATTERN);
	}
	
	/**
	 * 验证是否是中文
	 * @param value
	 * @return
	 */
	public static boolean parseCNword(String value) {
		return customParse(value, WORD_CN_PATTERN);
	}
	
	/**
	 * 按照客户自定义的格式来验证用户输入的数据是否匹配<p>
	 *    
	 * 字符  <p>
	 * x 字符 x  <br>
	 * \\ 反斜线字符  <br>
	 * \0n 带有八进制值 0 的字符 n (0 <= n <= 7)  <br>
	 * \0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)  <br>
	 * \0mnn 带有八进制值 0 的字符 mnn（0 <= m <= 3、0 <= n <= 7）  <br>
	 * \xhh 带有十六进制值 0x 的字符 hh  <br>
	 * /uhhhh (特别注意：此处的斜杠应为反斜杠)带有十六进制值 0x 的字符 hhhh  <br>
	 * \t 制表符 ('\u0009')  <br>
	 * \n 新行（换行）符 ('\u000A')  <br>
	 * \r 回车符 ('\u000D')  <br>
	 * \f 换页符 ('\u000C')  <br>
	 * \a 报警 (bell) 符 ('\u0007')  <br>
	 * \e 转义符 ('\u001B')  <br>
	 * \cx 对应于 x 的控制符  <br>
	 *    <p>
	 * 字符类  <p>
	 * [abc] a、b 或 c（简单类）  <br>
	 * [^abc] 任何字符，除了 a、b 或 c（否定）  <br>
	 * [a-zA-Z] a 到 z 或 A 到 Z，两头的字母包括在内（范围）  <br>
	 * [a-d[m-p]] a 到 d 或 m 到 p：[a-dm-p]（并集）  <br>
	 * [a-z&&[def]] d、e 或 f（交集）  <br>
	 * [a-z&&[^bc]] a 到 z，除了 b 和 c：[ad-z]（减去）  <br>
	 * [a-z&&[^m-p]] a 到 z，而非 m 到 p：[a-lq-z]（减去）  <br>
	 *    <p>
	 * 预定义字符类  <p>
	 * . 任何字符（与行结束符可能匹配也可能不匹配）  <br>
	 * \d 数字：[0-9]  <br>
	 * \D 非数字： [^0-9]  <br>
	 * \s 空白字符：[ \t\n\x0B\f\r]  <br>
	 * \S 非空白字符：[^\s]  <br>
	 * \w 单词字符：[a-zA-Z_0-9]  <br>
	 * \W 非单词字符：[^\w]  <br>
	 *    <p>
	 * POSIX 字符类（仅 US-ASCII）  <p>
	 * \p{Lower} 小写字母字符：[a-z]  <br>
	 * \p{Upper} 大写字母字符：[A-Z]  <br>
	 * \p{ASCII} 所有 ASCII：[\x00-\x7F]  <br>
	 * \p{Alpha} 字母字符：[\p{Lower}\p{Upper}]  <br>
	 * \p{Digit} 十进制数字：[0-9]  <br>
	 * \p{Alnum} 字母数字字符：[\p{Alpha}\p{Digit}]  <br>
	 * \p{Punct} 标点符号：!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~  <br>
	 * \p{Graph} 可见字符：[\p{Alnum}\p{Punct}]  <br>
	 * \p{Print} 可打印字符：[\p{Graph}\x20]  <br>
	 * \p{Blank} 空格或制表符：[ \t]  <br>
	 * \p{Cntrl} 控制字符：[\x00-\x1F\x7F]  <br>
	 * \p{XDigit} 十六进制数字：[0-9a-fA-F]  <br>
	 * \p{Space} 空白字符：[ \t\n\x0B\f\r]  <br>
	 *    <p>
	 * java.lang.Character 类（简单的 java 字符类型）  <p>
	 * \p{javaLowerCase} 等效于 java.lang.Character.isLowerCase()  <br>
	 * \p{javaUpperCase} 等效于 java.lang.Character.isUpperCase()  <br>
	 * \p{javaWhitespace} 等效于 java.lang.Character.isWhitespace()  <br>
	 * \p{javaMirrored} 等效于 java.lang.Character.isMirrored()  <br>
	 *    <p>
	 * Unicode 块和类别的类  <p>
	 * \p{InGreek} Greek 块（简单块）中的字符  <br>
	 * \p{Lu} 大写字母（简单类别）  <br>
	 * \p{Sc} 货币符号  <br>
	 * \P{InGreek} 所有字符，Greek 块中的除外（否定）  <br>
	 * [\p{L}&&[^\p{Lu}]]  所有字母，大写字母除外（减去）  <br>
	 *    <p>
	 * 边界匹配器  <p>
	 * ^ 行的开头  <br>
	 * $ 行的结尾  <br>
	 * \b 单词边界  <br>
	 * \B 非单词边界  <br>
	 * \A 输入的开头  <br>
	 * \G 上一个匹配的结尾  <br>
	 * \Z 输入的结尾，仅用于最后的结束符（如果有的话）  <br>
	 * \z 输入的结尾  <br>
	 *    <p>
	 * Greedy 数量词  <p>
	 * X? X，一次或一次也没有  <br>
	 * X* X，零次或多次  <br>
	 * X+ X，一次或多次  <br>
	 * X{n} X，恰好 n 次  <br>
	 * X{n,} X，至少 n 次  <br>
	 * X{n,m} X，至少 n 次，但是不超过 m 次  <br>
	 *    <p>
	 * Reluctant 数量词  <p>
	 * X?? X，一次或一次也没有  <br>
	 * X*? X，零次或多次  <br>
	 * X+? X，一次或多次  <br>
	 * X{n}? X，恰好 n 次  <br>
	 * X{n,}? X，至少 n 次  <br>
	 * X{n,m}? X，至少 n 次，但是不超过 m 次  <br>
	 *    <p>
	 * Possessive 数量词  <p>
	 * X?+ X，一次或一次也没有  <br>
	 * X*+ X，零次或多次  <br>
	 * X++ X，一次或多次  <br>
	 * X{n}+ X，恰好 n 次  <br>
	 * X{n,}+ X，至少 n 次  <br>
	 * X{n,m}+ X，至少 n 次，但是不超过 m 次  <br>
	 *    <p>
	 * Logical 运算符  <p>
	 * XY X 后跟 Y  <br>
	 * X|Y X 或 Y  <br>
	 * (X) X，作为捕获组  <br>
	 *    <p>
	 * Back 引用  <p>
	 * \n 任何匹配的 nth 捕获组  <br>
	 *    <p>
	 * 引用  <p>
	 * \ Nothing，但是引用以下字符  <br>
	 * \Q Nothing，但是引用所有字符，直到 \E  <br>
	 * \E Nothing，但是结束从 \Q 开始的引用  <br>
	 *    <p>
	 * 特殊构造（非捕获）  <p>
	 * (?:X) X，作为非捕获组  <br>
	 * (?idmsux-idmsux)  Nothing，但是将匹配标志i d m s u x on - off  <br>
	 * (?idmsux-idmsux:X)   X，作为带有给定标志 i d m s u x on - off  <br>
	 * (?=X) X，通过零宽度的正 lookahead  <br>
	 * (?!X) X，通过零宽度的负 lookahead  <br>
	 * (?<=X) X，通过零宽度的正 lookbehind  <br>
	 * (?<!X) X，通过零宽度的负 lookbehind  <br>
	 * (?>X) X，作为独立的非捕获组  <br>
	 * @param data
	 * @param pattern
	 * @return
	 */
	public static boolean customParse(String data, String pattern) {
		try {
			Pattern p=Pattern.compile(pattern);
			Matcher m = p.matcher(data);
			return m.matches();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 验证用户输入的数据是否 <b>包含</b> 用户定义格式的字符串<p>
	 *    
	 * 字符  <p>
	 * x 字符 x  <br>
	 * \\ 反斜线字符  <br>
	 * \0n 带有八进制值 0 的字符 n (0 <= n <= 7)  <br>
	 * \0nn 带有八进制值 0 的字符 nn (0 <= n <= 7)  <br>
	 * \0mnn 带有八进制值 0 的字符 mnn（0 <= m <= 3、0 <= n <= 7）  <br>
	 * \xhh 带有十六进制值 0x 的字符 hh  <br>
	 * /uhhhh (特别注意：此处的斜杠应为反斜杠)带有十六进制值 0x 的字符 hhhh  <br>
	 * \t 制表符 ('\u0009')  <br>
	 * \n 新行（换行）符 ('\u000A')  <br>
	 * \r 回车符 ('\u000D')  <br>
	 * \f 换页符 ('\u000C')  <br>
	 * \a 报警 (bell) 符 ('\u0007')  <br>
	 * \e 转义符 ('\u001B')  <br>
	 * \cx 对应于 x 的控制符  <br>
	 *    <p>
	 * 字符类  <p>
	 * [abc] a、b 或 c（简单类）  <br>
	 * [^abc] 任何字符，除了 a、b 或 c（否定）  <br>
	 * [a-zA-Z] a 到 z 或 A 到 Z，两头的字母包括在内（范围）  <br>
	 * [a-d[m-p]] a 到 d 或 m 到 p：[a-dm-p]（并集）  <br>
	 * [a-z&&[def]] d、e 或 f（交集）  <br>
	 * [a-z&&[^bc]] a 到 z，除了 b 和 c：[ad-z]（减去）  <br>
	 * [a-z&&[^m-p]] a 到 z，而非 m 到 p：[a-lq-z]（减去）  <br>
	 *    <p>
	 * 预定义字符类  <p>
	 * . 任何字符（与行结束符可能匹配也可能不匹配）  <br>
	 * \d 数字：[0-9]  <br>
	 * \D 非数字： [^0-9]  <br>
	 * \s 空白字符：[ \t\n\x0B\f\r]  <br>
	 * \S 非空白字符：[^\s]  <br>
	 * \w 单词字符：[a-zA-Z_0-9]  <br>
	 * \W 非单词字符：[^\w]  <br>
	 *    <p>
	 * POSIX 字符类（仅 US-ASCII）  <p>
	 * \p{Lower} 小写字母字符：[a-z]  <br>
	 * \p{Upper} 大写字母字符：[A-Z]  <br>
	 * \p{ASCII} 所有 ASCII：[\x00-\x7F]  <br>
	 * \p{Alpha} 字母字符：[\p{Lower}\p{Upper}]  <br>
	 * \p{Digit} 十进制数字：[0-9]  <br>
	 * \p{Alnum} 字母数字字符：[\p{Alpha}\p{Digit}]  <br>
	 * \p{Punct} 标点符号：!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~  <br>
	 * \p{Graph} 可见字符：[\p{Alnum}\p{Punct}]  <br>
	 * \p{Print} 可打印字符：[\p{Graph}\x20]  <br>
	 * \p{Blank} 空格或制表符：[ \t]  <br>
	 * \p{Cntrl} 控制字符：[\x00-\x1F\x7F]  <br>
	 * \p{XDigit} 十六进制数字：[0-9a-fA-F]  <br>
	 * \p{Space} 空白字符：[ \t\n\x0B\f\r]  <br>
	 *    <p>
	 * java.lang.Character 类（简单的 java 字符类型）  <p>
	 * \p{javaLowerCase} 等效于 java.lang.Character.isLowerCase()  <br>
	 * \p{javaUpperCase} 等效于 java.lang.Character.isUpperCase()  <br>
	 * \p{javaWhitespace} 等效于 java.lang.Character.isWhitespace()  <br>
	 * \p{javaMirrored} 等效于 java.lang.Character.isMirrored()  <br>
	 *    <p>
	 * Unicode 块和类别的类  <p>
	 * \p{InGreek} Greek 块（简单块）中的字符  <br>
	 * \p{Lu} 大写字母（简单类别）  <br>
	 * \p{Sc} 货币符号  <br>
	 * \P{InGreek} 所有字符，Greek 块中的除外（否定）  <br>
	 * [\p{L}&&[^\p{Lu}]]  所有字母，大写字母除外（减去）  <br>
	 *    <p>
	 * 边界匹配器  <p>
	 * ^ 行的开头  <br>
	 * $ 行的结尾  <br>
	 * \b 单词边界  <br>
	 * \B 非单词边界  <br>
	 * \A 输入的开头  <br>
	 * \G 上一个匹配的结尾  <br>
	 * \Z 输入的结尾，仅用于最后的结束符（如果有的话）  <br>
	 * \z 输入的结尾  <br>
	 *    <p>
	 * Greedy 数量词  <p>
	 * X? X，一次或一次也没有  <br>
	 * X* X，零次或多次  <br>
	 * X+ X，一次或多次  <br>
	 * X{n} X，恰好 n 次  <br>
	 * X{n,} X，至少 n 次  <br>
	 * X{n,m} X，至少 n 次，但是不超过 m 次  <br>
	 *    <p>
	 * Reluctant 数量词  <p>
	 * X?? X，一次或一次也没有  <br>
	 * X*? X，零次或多次  <br>
	 * X+? X，一次或多次  <br>
	 * X{n}? X，恰好 n 次  <br>
	 * X{n,}? X，至少 n 次  <br>
	 * X{n,m}? X，至少 n 次，但是不超过 m 次  <br>
	 *    <p>
	 * Possessive 数量词  <p>
	 * X?+ X，一次或一次也没有  <br>
	 * X*+ X，零次或多次  <br>
	 * X++ X，一次或多次  <br>
	 * X{n}+ X，恰好 n 次  <br>
	 * X{n,}+ X，至少 n 次  <br>
	 * X{n,m}+ X，至少 n 次，但是不超过 m 次  <br>
	 *    <p>
	 * Logical 运算符  <p>
	 * XY X 后跟 Y  <br>
	 * X|Y X 或 Y  <br>
	 * (X) X，作为捕获组  <br>
	 *    <p>
	 * Back 引用  <p>
	 * \n 任何匹配的 nth 捕获组  <br>
	 *    <p>
	 * 引用  <p>
	 * \ Nothing，但是引用以下字符  <br>
	 * \Q Nothing，但是引用所有字符，直到 \E  <br>
	 * \E Nothing，但是结束从 \Q 开始的引用  <br>
	 *    <p>
	 * 特殊构造（非捕获）  <p>
	 * (?:X) X，作为非捕获组  <br>
	 * (?idmsux-idmsux)  Nothing，但是将匹配标志i d m s u x on - off  <br>
	 * (?idmsux-idmsux:X)   X，作为带有给定标志 i d m s u x on - off  <br>
	 * (?=X) X，通过零宽度的正 lookahead  <br>
	 * (?!X) X，通过零宽度的负 lookahead  <br>
	 * (?<=X) X，通过零宽度的正 lookbehind  <br>
	 * (?<!X) X，通过零宽度的负 lookbehind  <br>
	 * (?>X) X，作为独立的非捕获组  <br>
	 * @param data
	 * @param pattern
	 * @return
	 */
	public static boolean customParseContains(String data, String pattern) {
		try {
			Pattern p=Pattern.compile(pattern);
			Matcher m = p.matcher(data);
			return m.find();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
		return false;
	}
}
